﻿using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;
using System.IO;
using SuSPExtension;

/// <summary>
/// 一共可选择三种样式
/// </summary>
public enum enumWinStyle
{
    /// <summary>
    /// 置顶
    /// </summary>
    WinTop,
    /// <summary>
    /// 置顶并且透明
    /// </summary>
    WinTopApha,
    /// <summary>
    /// 置顶透明并且可以穿透
    /// </summary>
    WinTopAphaPenetrate
}
public class WinSetting : MonoSingleton<WinSetting>
{

    #region Win函数常量
    private struct MARGINS
    {
        public int cxLeftWidth;
        public int cxRightWidth;
        public int cyTopHeight;
        public int cyBottomHeight;
    }

    [DllImport("user32.dll")]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    [DllImport("user32.dll")]
    static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll")]
    static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

    [DllImport("user32.dll")]
    static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, int bAlpha, int dwFlags);

    [DllImport("Dwmapi.dll")]
    static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
    private const int WS_POPUP = 0x800000;
    private const int GWL_EXSTYLE = -20;
    private const int GWL_STYLE = -16;
    private const int WS_EX_LAYERED = 0x00080000;
    private const int WS_BORDER = 0x00800000;
    private const int WS_CAPTION = 0x00C00000;
    private const int SWP_SHOWWINDOW = 0x0040;
    private const int LWA_COLORKEY = 0x00000001;
    private const int LWA_ALPHA = 0x00000002;
    private const int WS_EX_TRANSPARENT = 0x20;
    //
    private const int ULW_COLORKEY = 0x00000001;
    private const int ULW_ALPHA = 0x00000002;
    private const int ULW_OPAQUE = 0x00000004;
    private const int ULW_EX_NORESIZE = 0x00000008;
    #endregion

    public string strProduct;//项目名称
    public enumWinStyle WinStyle = enumWinStyle.WinTop;//窗体样式

    private bool isApha;//是否透明
    private bool isAphaPenetrate;//是否要穿透窗体

    private int windowBeginState;
    private IntPtr hwnd;
    public SystemWindow syswin;
    public GameObject mainPanel;

    float hwradio; //高宽比
    float targetHeight, targetWidth,targetPosX,targetPosY;
    
    Vector2 curPos, curSize;
    int curAlpha;
    PackageData configdata;
    bool isNeedAlphaFade; //鼠标滑入时是否需要过渡
    float targetAlphaFadeValue = 200;
    float currentAlphaFadeTarget;//当前的窗口的目标Alpha
    bool isShoundActiveWindow; //是否应该激活窗口

    protected override void Awake()
    {
        base.Awake();

        Application.targetFrameRate = 24;
        configdata = AppDataManager.Instance.GetCurrentPackageInfo();
        PackageConfig windata = configdata.packageConfig;
        WinStyle = windata.winStyle;
        SuSPExtension.Rect rect = SystemUtil.GetDeviceMainScreenResulution();
        curAlpha = windata.winAlpha;

        targetPosX = windata.PosX;
        targetPosY = windata.PosY;
        targetWidth = windata.winScalePercent;
        targetHeight = windata.winScalePercent;

        hwnd = FindWindow(null, strProduct);
        syswin = new SystemWindow(hwnd.ToString());
        syswin.Alpha = (byte)curAlpha;
        windowBeginState = GetWindowLong(hwnd, GWL_EXSTYLE);
        hwradio = (float)rect.height / rect.width;


        if (Application.platform == RuntimePlatform.WindowsPlayer)
        {
            switch (WinStyle)
            {
                case enumWinStyle.WinTop:
                    isApha = false;
                    isAphaPenetrate = false;
                    break;
                case enumWinStyle.WinTopApha:
                    isApha = true;
                    isAphaPenetrate = false;
                    break;
                case enumWinStyle.WinTopAphaPenetrate:
                    isApha = true;
                    isAphaPenetrate = true;
                    break;
            }

            if (isApha)
            {
                //去边框并且透明
                SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED);
                if (isAphaPenetrate)//是否透明穿透窗体
                {
                    SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_TRANSPARENT | WS_EX_LAYERED);
                }
                SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_BORDER & ~WS_CAPTION);
                SetWindowPos(hwnd, -1, 0, 0, rect.width, rect.height, SWP_SHOWWINDOW);
                var margins = new MARGINS() { cxLeftWidth = -1 };
                DwmExtendFrameIntoClientArea(hwnd, ref margins);
            }
            else
            {
                //单纯去边框
                SetWindowLong(hwnd, GWL_STYLE, WS_POPUP);
                SetWindowPos(hwnd, -1, 0, 0, rect.width, rect.height, SWP_SHOWWINDOW);
            }
        }       
    }

    protected override void Init()
    {
        base.Init();
        EventBus.Instance.AddEventHandler(EventID.On_Paper_RefreshFinished, OnPackageChange);
    }

    private void WindowPenetrateRestore()
    {
        SetWindowLong(hwnd, GWL_EXSTYLE, windowBeginState | WS_EX_LAYERED);
    }

    private void WindowPenetrate()
    {
        SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED);
        if (isAphaPenetrate)//是否透明穿透窗体
        {
            SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_TRANSPARENT | WS_EX_LAYERED);
        }
    }

    private bool IsHoverOnFocusArea(Vector3 screenpos)
    {
        Vector3 viewpos = Camera.main.ScreenToViewportPoint(screenpos);
        return viewpos.x > 0.8f && viewpos.y > 0.8f && viewpos.x <= 1f && viewpos.y <= 1f;
    }

    public void OnPackageChange()
    {
        //切换了package后这里需要重新获取
        configdata = AppDataManager.Instance.GetCurrentPackageInfo();
        targetPosX = configdata.packageConfig.PosX;
        targetPosY = configdata.packageConfig.PosY;
    }

    private void Update()
    {
        //切换了package后这里需要重新获取
        configdata = AppDataManager.Instance.GetCurrentPackageInfo();

        if (configdata.packageConfig.isWinAutoActive)
        {
            Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1);
            if (IsHoverOnFocusArea(mousePos))
            {
                if (!isShoundActiveWindow)
                {
                    //经测试，Active方法有可能一次执行不成功，所以这里多次进行Active
                    //但是一定要避免死循环
                    //经测试，surface pro4上激活方法不起作用，有待修复
                    int loopCount = 0;
                    isShoundActiveWindow = true;
                    while (!syswin.IsFocus())
                    {
                        loopCount++;
                        if (loopCount > 100)
                            break;
                        syswin.Activate();
                    }
                    //AppManager.Instance.Tip = "窗口激活:" + syswin.IsFocus();
                }
            }
            else
            {
                isShoundActiveWindow = false;
            }
        }

        //鼠标滑过时变透明
        if (configdata.packageConfig.isTransparentWhenHover)
        {
            Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1);
            if (Utils.IsEnterView(mousePos))
            {
                if (!isNeedAlphaFade)
                {
                    isNeedAlphaFade = true;
                    if (curAlpha >= targetAlphaFadeValue)
                    {
                        currentAlphaFadeTarget = targetAlphaFadeValue;
                    }
                }
            }
            else
            {
                currentAlphaFadeTarget = configdata.packageConfig.winAlpha;
                isNeedAlphaFade = false;
            }
        }
        else
        {
            currentAlphaFadeTarget = configdata.packageConfig.winAlpha;
        }

        if (Input.GetKeyDown(KeyCode.H))
        {
            mainPanel.SetActive(!mainPanel.activeInHierarchy);
            if (mainPanel.activeInHierarchy)
            {
                WindowPenetrateRestore();
            }
            else
            {
                WindowPenetrate();
            }
        }

        float targetPosChangeSpeed = 0.5f;
        if (Input.GetKey(KeyCode.LeftShift))
        {
            targetPosChangeSpeed = 0.1f;
        }

        if (Input.GetKey(KeyCode.RightArrow))
        {
            targetPosX += Time.deltaTime * targetPosChangeSpeed;
            configdata.packageConfig.PosX = targetPosX;
        }

        if (Input.GetKey(KeyCode.LeftArrow))
        {
            targetPosX -= Time.deltaTime * targetPosChangeSpeed;
            configdata.packageConfig.PosX = targetPosX;
        }

        if (Input.GetKey(KeyCode.UpArrow))
        {
            targetPosY += Time.deltaTime * targetPosChangeSpeed;
            configdata.packageConfig.PosY = targetPosY;
        }

        if (Input.GetKey(KeyCode.DownArrow))
        {
            targetPosY -= Time.deltaTime * targetPosChangeSpeed;
            configdata.packageConfig.PosY = targetPosY;
        }

        targetWidth = configdata.packageConfig.winScalePercent;
        targetHeight = configdata.packageConfig.winScalePercent;

        curSize = Vector2.Lerp(curSize, new Vector2(targetWidth, targetHeight), 0.8f);
        curPos = Vector2.Lerp(curPos, new Vector2(targetPosX - targetWidth * 0.5f, targetPosY - targetHeight * 0.5f), 0.8f);
        Camera.main.rect = new UnityEngine.Rect(curPos, curSize);

        currentAlphaFadeTarget = Mathf.Clamp(currentAlphaFadeTarget, 20, 255);
        curAlpha = (int)Mathf.Lerp(curAlpha, currentAlphaFadeTarget, 10 * Time.deltaTime);
        syswin.Alpha = (byte)curAlpha;

        SuSPExtension.Rect rect = SystemUtil.GetDeviceMainScreenResulution();
        SetWindowPos(hwnd, -1, 0, 0, rect.width, rect.height, SWP_SHOWWINDOW);
    }

}